package cn.bfay.lion.jingdong.helper;

import cn.bfay.lion.jingdong.client.rsp.JdProductInfo;
import cn.bfay.lion.jingdong.enums.CouponType;
import cn.bfay.lion.jingdong.enums.PlusType;
import cn.bfay.lion.jingdong.enums.PromotionType;
import cn.bfay.lion.util.NumberUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 商品计算帮助类.
 *
 * @author wangjiannan
 */
@Slf4j
public class ProductCalculateHelper {

    public static ProductCalculate calculate(CalculateType calculateType, JdProductInfo jdProductInfo) {
        double price;
        double plusDiscount;
        if (calculateType == CalculateType.NORMAL_PRICE) {
            price = jdProductInfo.getNormalPrice();
            plusDiscount = 1.0;
        } else if (calculateType == CalculateType.PLUS_PRICE) {
            price = jdProductInfo.getPlusPrice();
            if (PlusType.NONE.getCode() == jdProductInfo.getPlusType()) {
                plusDiscount = 1.0;
            } else if (PlusType.DISCOUNT.getCode() == jdProductInfo.getPlusType()) {
                plusDiscount = jdProductInfo.getPlusDiscount();
            } else {
                throw new RuntimeException("价格计算失败,请排查......");
            }
        } else {
            throw new RuntimeException("价格计算失败,请排查......");
        }

        int promotionType = jdProductInfo.getPromotionType();
        Double promotionFull = jdProductInfo.getPromotionFull();
        Double promotionMinus = jdProductInfo.getPromotionMinus();
        Double promotionCount = jdProductInfo.getPromotionCount();
        Double promotionDiscount = jdProductInfo.getPromotionDiscount();
        int couponType = jdProductInfo.getCouponType();
        Double couponFull = jdProductInfo.getCouponFull();
        Double couponMinus = jdProductInfo.getCouponMinus();
        Double couponDiscount = jdProductInfo.getCouponDiscount();

        double count;
        double allMoney;
        double finalPrice;
        // a.
        if (PromotionType.NONE.getCode() == promotionType && CouponType.NONE.getCode() == couponType) {
            count = 1;
            allMoney = price * count;
            finalPrice = (allMoney - allMoney * (1 - plusDiscount)) / count;
            return ProductCalculate.builder().price(finalPrice).count(count).build();
        }

        if (PromotionType.NONE.getCode() == promotionType && CouponType.FULL_MONEY_MINUS_MONEY.getCode() == couponType) {
            // pt:null      ct:99-20   price:150;50
            if (NumberUtils.doubleGtEquals(price, couponFull)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(couponFull / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.NONE.getCode() == promotionType && CouponType.FULL_MONEY_DISCOUNT.getCode() == couponType) {
            // pt:null      ct:99 10%   price:150;50
            if (NumberUtils.doubleGtEquals(price, couponFull)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(couponFull / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        // b.
        if (PromotionType.EVERY_FULL_MONEY_MINUS_MONEY.getCode() == promotionType && CouponType.NONE.getCode() == couponType) {
            // pt:60-5      ct:null   price:150;40
            if (NumberUtils.doubleGtEquals(price, promotionFull)) {
                count = 1;
                allMoney = price * count;
                double minusCount = Math.floor(price / promotionFull);
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - minusCount * promotionMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(promotionFull / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - promotionMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.EVERY_FULL_MONEY_MINUS_MONEY.getCode() == promotionType && CouponType.FULL_MONEY_MINUS_MONEY.getCode() == couponType) {
            // pt:80-10      ct:90-10   price:100;85;80;30
            double max = NumberUtils.getMaxDouble(couponFull, promotionFull);
            if (NumberUtils.doubleGtEquals(price, max)) {
                count = 1;
                allMoney = price * count;
                double minusCount = Math.floor(price / promotionFull);
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - minusCount * promotionMinus - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(max / price);
                allMoney = price * count;
                double minusCount = Math.floor(allMoney / promotionFull);
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - minusCount * promotionMinus - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.EVERY_FULL_MONEY_MINUS_MONEY.getCode() == promotionType && CouponType.FULL_MONEY_DISCOUNT.getCode() == couponType) {
            // pt:80-10      ct:90 9折   price:200;85;80;30
            double max = NumberUtils.getMaxDouble(couponFull, promotionFull);
            if (NumberUtils.doubleGtEquals(price, max)) {
                count = 1;
                allMoney = price * count;
                double minusCount = Math.floor(allMoney / promotionFull);
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - minusCount * promotionMinus - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(max / price);
                allMoney = price * count;
                double minusCount = Math.floor(allMoney / promotionFull);
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - minusCount * promotionMinus - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        // c.
        if (PromotionType.FULL_MONEY_MINUS_MONEY.getCode() == promotionType && CouponType.NONE.getCode() == couponType) {
            // pt:60-5      ct:null   price:150;40
            if (NumberUtils.doubleGtEquals(price, promotionFull)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - promotionMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(promotionFull / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - promotionMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.FULL_MONEY_MINUS_MONEY.getCode() == promotionType && CouponType.FULL_MONEY_MINUS_MONEY.getCode() == couponType) {
            // pt:80-10      ct:90-10   price:100;85;80;30
            double max = NumberUtils.getMaxDouble(couponFull, promotionFull);
            if (NumberUtils.doubleGtEquals(price, max)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - promotionMinus - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(max / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - promotionMinus - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.FULL_MONEY_MINUS_MONEY.getCode() == promotionType && CouponType.FULL_MONEY_DISCOUNT.getCode() == couponType) {
            // pt:80-10      ct:90 8折   price:100;85;80;30
            double max = NumberUtils.getMaxDouble(couponFull, promotionFull);
            if (NumberUtils.doubleGtEquals(price, max)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - promotionMinus - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(max / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - promotionMinus - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        // d.
        if (PromotionType.FULL_COUNT_DISCOUNT.getCode() == promotionType && CouponType.NONE.getCode() == couponType) {
            // pt:3件 7折      ct:null   price:150;40
            count = promotionCount;
            allMoney = price * count;
            finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount)) / count;
            return ProductCalculate.builder().price(finalPrice).count(count).build();
        }

        if (PromotionType.FULL_COUNT_DISCOUNT.getCode() == promotionType && CouponType.FULL_MONEY_MINUS_MONEY.getCode() == couponType) {
            // pt:3件 7折      ct:90-10   price:150;20
            if (NumberUtils.doubleGtEquals(price * promotionCount, couponFull)) {
                count = promotionCount;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(couponFull / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.FULL_COUNT_DISCOUNT.getCode() == promotionType && CouponType.FULL_MONEY_DISCOUNT.getCode() == couponType) {
            // pt:3件 7折      ct:90 8折  price:150;20
            if (NumberUtils.doubleGtEquals(price * promotionCount, couponFull)) {
                count = promotionCount;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(couponFull / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        // e.
        if (PromotionType.FULL_MONEY_DISCOUNT.getCode() == promotionType && CouponType.NONE.getCode() == couponType) {
            // pt:60 7折      ct:null   price:150;40
            if (NumberUtils.doubleGtEquals(price, promotionFull)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(promotionFull / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.FULL_MONEY_DISCOUNT.getCode() == promotionType && CouponType.FULL_MONEY_MINUS_MONEY.getCode() == couponType) {
            // pt:80 9折     ct:90-10   price:100;85;80;30
            double max = NumberUtils.getMaxDouble(couponFull, promotionFull);
            if (NumberUtils.doubleGtEquals(price, max)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(max / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - couponMinus) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        if (PromotionType.FULL_MONEY_DISCOUNT.getCode() == promotionType && CouponType.FULL_MONEY_DISCOUNT.getCode() == couponType) {
            // pt:80 9折     ct:90 9折   price:100;85;80;30
            double max = NumberUtils.getMaxDouble(couponFull, promotionFull);
            if (NumberUtils.doubleGtEquals(price, max)) {
                count = 1;
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            } else {
                count = Math.ceil(max / price);
                allMoney = price * count;
                finalPrice = (allMoney - allMoney * (1 - plusDiscount) - allMoney * (1 - promotionDiscount) - allMoney * (1 - couponDiscount)) / count;
                return ProductCalculate.builder().price(finalPrice).count(count).build();
            }
        }

        throw new RuntimeException("价格计算失败,请排查......");
    }
}
